package org.ribizli.basicgameserver.data;


import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Table;

import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.annotations.CollectionOfElements;
import org.hibernate.annotations.MapKey;
import org.ribizli.basicgameserver.AmoebaGame;


@Entity
@Table(name="amoeba_users")
public class User implements Serializable {
	private static final long serialVersionUID = -7140150449526591324L;
	private Long id;
	private String username;
	private String password;
	private Integer score = 1500;
	private HashMap<String, String> details;
	
	@Id @GeneratedValue(strategy=GenerationType.AUTO)
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	
	@Column(unique=true, nullable=false, length=50)
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	
	@Column(nullable=false, length=50)
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	
	public Integer getScore() {
		return score;
	}
	public void setScore(Integer score) {
	  if (score < 0) score = 0;
		this.score = score;
	}
	
	@CollectionOfElements(fetch=FetchType.LAZY)
	@MapKey(columns=@Column(name="propertyKey"))
	@JoinTable(name="amoeba_user_prop", joinColumns=@JoinColumn(name="id"))
	@Column(name="propertyValue")
	public Map<String, String> getDetails() {
		return details;
	}
	public void setDetails(Map<String, String> details) {
		this.details = new HashMap<String, String>(details);
	}
	
	public static User findUser(String username) {
		Session s = HibernateUtil.getSession();
		User u = null;
		try {
	    u = (User) s.createQuery("from User as user where user.username = ?").setString(0, username).uniqueResult();
	    Hibernate.initialize(u);
		} finally {
			s.close();
		}
    return u;
	}
	
	public void save() {
		Session s = HibernateUtil.getSession();
		try {
			s.beginTransaction();
			s.saveOrUpdate(this);
			s.getTransaction().commit();
		} catch (HibernateException e) {
			s.getTransaction().rollback();
			throw e;
		} finally {
			s.close();
		}
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj) return true;
		if (!(obj instanceof User)) return false;
		User that = (User)obj;
		return this.getId() != null && that.getId() != null && this.getId().equals(that.getId());
	}
	@Override
	public int hashCode() {
		return this.getId().hashCode();
	}
	
	public void hasBeaten(User opp) {
	  int won = opp.getScore() / 50;
	  this.setScore(this.getScore() + won);
    opp.setScore(opp.getScore() - won);
    this.save();
    opp.save();
	}
	
	public boolean checkPassword(String password) {
		return this.password.equals(SHA1(password));
	}
	
	public static String SHA1(String word) {
		String sha1 = null;
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			byte[] digest = md.digest(word.getBytes("UTF8"));
			StringBuffer hexString = new StringBuffer();
			for (int i = 0; i < digest.length; i++) {
				String hex = Integer.toHexString(0xFF & digest[i]);
				if (hex.length() == 1) {
					hexString.append('0');
				}
				hexString.append(hex);
			}
			sha1 = hexString.toString();
		} catch (NoSuchAlgorithmException e) {
		} catch (UnsupportedEncodingException e) {
		}
		return sha1;
	}
}
